package com.xtm.exercise.base.A15jdk8Demo.java8;


import cn.hutool.core.util.ObjectUtil;
import com.xtm.exercise.base.B09copyBean.po.User;
import org.junit.Test;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

/**
 *  Optional 类主要解决的问题是臭名昭著的空指针异常（NullPointerException）
 *
 *          if (user != null) {
 *             Address address = user.getAddress();
 *             if (address != null) {
 *                 Country country = address.getCountry();
 *                 if (country != null) {
 *                     String isocode = country.getIsocode();
 *                     if (isocode != null) {
 *                         isocode = isocode.toUpperCase();
 *                     }
 *                 }
 *             }
 *         }
 */
public class OptionalDemo {

    @Test
    public void test00001(){
        // 解决get方法空指针
        Student student = null;
        // 解决get方法空指针   如果对象是空，get方法空指针
        String name1 = Optional.ofNullable(student).map(Student::getName).orElse(null);
        System.out.println(name1);

        // 如果不使用Optional，get方法会空指针
        String name2 = student.getName();
        System.out.println(name2);

//        BigDecimal differenceWeight = Optional.ofNullable(orderGoodsMeasureBO.getRealDsptGoodsMeasuring().getWeight())
//                .map(x -> x.subtract(weight))
//                .orElse(BigDecimal.ZERO);
    }

    @Test
    public void test000(){
        Student student = null;
//        student.setAge(19);
//        Student student = null;
        // 创建Optional类  --  empty \  of \  ofNullable
        Optional<Student> optional = Optional.ofNullable(student);
        if(ObjectUtil.isNotEmpty(student)){
            System.out.println("student1 = null");
        } else {
            System.out.println(student);
        }

    }

    @Test
    public void test11(){
//        Student student = new Student();
        Student student = null;
        // 创建Optional类  --  empty \  of \  ofNullable
        Optional<Student> optional = Optional.ofNullable(student);
        System.out.println(optional);

        // 判断Optional容器中是否包含对象  --  isPresent  --  ifPresent
        // isPresent不带参数，判断是否为空，ifPresent可以选择带一个消费函数的实例。（isPresent和ifPresent一个是 is 一个是 if 注意一下哈）
        Optional.ofNullable(student).ifPresent(p -> p.setName("张三"));

        // 获取Optional容器的对象 --  orElse  /  orElseThrow  /
        Student student1 = Optional.ofNullable(student).orElse(null);
        System.out.println(student1);

        // 过滤  -- filter
        Optional.ofNullable(student).filter(p -> p.getName().equals("张三")).ifPresent(p -> p.setAge(19));
        System.out.println(student);
        // 映射 --  map
        String s = Optional.ofNullable(student).map(Student::getName).orElse(null);
        Integer integer = Optional.ofNullable(student).map(Student::getAge).orElse(null);
        System.out.println(integer);
        System.out.println(s);

        // 如果不使用Optional，get方法会空指针
        String name = student.getName();
        System.out.println(name);

        // 类型之间的转换，并且当没有值的时候返回一个默认值
        Optional<Integer> optionalInteger = Optional.ofNullable(student).map(x -> x.getAge().intValue());
        Integer age = optionalInteger.orElse(null);
        System.out.println(age);
    }

    @Test
    public void test04(){
//        重申一下，这个类型的对象可能包含值，也可能为空。你可以使用同名方法创建一个空的 Optional。
        Optional<User> emptyOpt = Optional.empty();
        emptyOpt.get();
        //尝试访问 emptyOpt 变量的值会导致 NoSuchElementException。
    }


     /*创建 Optional  实例
     可以使用  of() 和 ofNullable() 方法创建包含值的 Optional。
     两个方法的不同之处在于如果你把 null 值作为参数传递进去，of() 方法会抛出 NullPointerException：*/
    /**
     * 返回默认值 Optional.ofNullable(user).orElse(user2)
     * 用以返回对象值，或者在对象为空的时候返回默认值
     * orElse()，它的工作方式非常直接，如果有值则返回该值，否则返回传递给它的参数值
     */
    @Test
    public void test01() {
        //第一种情况，user不是null
//        User user = new User("李四","19","女");
        //第二种情况，user是null
        User user = null;

        User user2 = new User();
        user2.setName("wanglei");
        user2.setAge(2);

        User result = Optional.ofNullable(user).orElse(user2);
        System.out.println(result.toString());

//        分页-应用  项目中应用
//        int pageIndex = Optional.ofNullable(requestCondition.getPageIndex()).orElse(1);
//        int pageSize = Optional.ofNullable(requestCondition.getPageSize()).orElse(10);

    }

    /**
     * 返回异常
     * orElseThrow 如果有值则将其返回，否则在对象为空的时候抛出自定义异常，而不是返回备选的值。
     */
    @Test
    public void test02(){
        User user = null;
//        User user = new User("李四","19","女");
        User result = Optional.ofNullable(user)
                .orElseThrow( () -> new IllegalArgumentException());//java.lang.IllegalArgumentException
        System.out.println(result.toString());

//        Optional.ofNullable(oldUvmpRecDriver).orElseThrow(() -> new BizExecption("更新的驾驶员不存在"));
//        Optional.ofNullable(uvmpUser).orElseThrow(()-> new BizException("用户信息不存在"));
    }

//    /**
//     * 转换值  map()
//     */
//    @Test
//    public void test05(){
//        User user = new User("李四","19","女");
//        String username = Optional.ofNullable(user)
//                .map(u -> u.getUsername()).orElse("王五");
//
//        System.out.println(user);// 变成王五了
////        Assert.assertEquals(username, user.getUsername());
//    }

    /**
     * Optional 主要用作返回类型。在获取到这个类型的实例后，如果它有值，你可以取得这个值，否则可以进行一些替代行为。
     * Optional 类有一个非常有用的用例，就是将其与流或其它返回 Optional 的方法结合，以构建流畅的API。
     */
    @Test
    public void test06(){
        List<User> users = new ArrayList<>();
//        User user = users.stream().findFirst().get();//NoSuchElementException
        User user2 = new User();
        user2.setName("wanglei");
        user2.setAge(2);
        User user = users.stream().findFirst().orElse(user2);
        System.out.println(user.getName());
    }

    /**
     *      Optional.of(T t); // 创建一个Optional实例
     *      Optional.empty(); // 创建一个空的Optional实例
     *      Optional.ofNullable(T t); // 若T不为null，创建一个Optional实例，否则创建一个空实例
     *      isPresent();    // 判断是够包含值
     *      orElse(T t);   //如果调用对象包含值，返回该值，否则返回T
     *      orElseGet(Supplier s);  // 如果调用对象包含值，返回该值，否则返回s中获取的值
     *      map(Function f): // 如果有值对其处理，并返回处理后的Optional，否则返回Optional.empty();
     *      flatMap(Function mapper);// 与map类似。返回值是Optional
     *
     *      总结：Optional.of(null)  会直接报NPE
     */
    @Test
    public void test03(){
        User user2 = new User();
        user2.setName("wanglei");
        user2.setAge(19);
        Optional<User> op = Optional.ofNullable(user2);
        System.out.println(op.get());
    }
//    // NPE
//    Optional<Employee> op2 = Optional.of(null);
//        System.out.println(op2);
    @Test
    public void test2(){
        // 设置空对象
        Optional<Object> op = Optional.empty();
        System.out.println(op);

        // No value present
        System.out.println(op.get());

        User user2 = new User();
        user2.setName("wanglei");
        user2.setAge(19);
        Optional<User> op1 = Optional.ofNullable(user2);
//        System.out.println(op1.orElse(new User()));
//        System.out.println(op1.orElse(null));
    }
    @Test
    public void test3(){
        User user2 = new User();
        user2.setName("wanglei");
        user2.setAge(1);
        Optional<User> op = Optional.ofNullable(user2);
        User user = op.get();
        System.out.println();

        Optional<Object> op2 = Optional.ofNullable(null);
        System.out.println(op2);
        Object o = op2.get();
        // System.out.println(op2.get());
    }

    @Test
    public void test6(){
        User user2 = new User();
        user2.setName("wanglei");
        user2.setAge(19);
        Optional<User> op1 = Optional.ofNullable(user2);
        op1 = Optional.empty();
//        User employee = op1.orElseGet(() -> new User());
//        System.out.println(employee);
    }

    @Test
    public void test7(){
        User user2 = new User();
        user2.setName("wanglei");
        user2.setAge(19);
        Optional<User> op1 = Optional.ofNullable(user2);

        // 从对象里取值，如果是空的，设置返回null
        String userName = Optional.ofNullable(user2).map(e -> e.getName()).orElse(null);
        System.out.println(userName);

        // 从对象里取值，如果是空的，设置返回默认值
        String userName1 = Optional.ofNullable(user2).map(e -> e.getName()).orElse("wanglei");
        System.out.println(userName1);

    }
}
